﻿
//包含头文件
namespace n_Include
{
using System;
using System.IO;
using System.Text;

using n_Config;
using n_ET;
using n_UseFileList;
using n_VarType;
using i_Compiler;
using n_OS;
using n_CPUType;

public static class Include
{
	//注意不知道为什么在Init中建立RichTextBox导致编译内核不能在多进程下运行
	//初始化
	public static void Init()
	{
		//r = new RichTextBox();
		DefineNodeList.Init();
	}
	
	//软件退出
	public static void Close()
	{
		//r.Dispose();
	}
	
	//包含头文件,当Src为null时表示正常编译,从文件中加载,否则把Src作为源代码编译
	public static string IncludeAllFile( string CurrentFilePath )
	{
		string src = null;
		if( n_Compiler.Compiler.SimTempSource != null ) {
			src = n_Compiler.Compiler.SimTempSource;
		}
		else {
			src = Compiler.OpenIncludeFile( CurrentFilePath );
		}
		
		//清空文件列表
		UseFileList.Clear();
		Config.ChipNumber = 0;
		Config.ChipIndex = 0;
		DefineNodeList.Reset();
		
		//加载所有的包含文件
		src = LoadFiles( src, CurrentFilePath );
		
		//封装源代码, 注意,这里的 root 没有用到, 编译器会替换成定义的root
		//src = "unit root{public unit " + VarType.UserRootUnitName + "{" +  src + "}";
		src = "unit root{" +  src;
		
		//加载系统文件
		string FileName = n_Config.Config.Path_compiler + "CPU" + OS.PATH_S + "system.txt";
		string sys = Compiler.OpenCompileFile( FileName );
		src += ((char)1).ToString() + ((char)UseFileList.GetNumber()).ToString() + sys + ((char)2).ToString() + "}";
		UseFileList.Add( OS.CompileRoot + FileName );
		
		//分割文件列表
		UseFileList.SplitPath();
		
		if( Config.ChipNumber == 0 ) {
			ET.WriteLineError( 0, 0, "没有设置目标芯片, 无法编译代码" );
		}
		
		return src;
	}
	
	//加载包含的文件,解析当前文件包含的所有文件
	static string LoadFiles( string src, string CurrentFilePath )
	{
		int FileIndex = UseFileList.GetNumber();
		
		//添加当前文件路径
		UseFileList.Add( CurrentFilePath );
		
		//获取所在的文件夹
		string CurrentDir = CurrentFilePath.Remove( CurrentFilePath.LastIndexOf( @"\" ) + 1 );
		
		string[] Cut = src.Split( '\n' );
		StringBuilder Source = new StringBuilder();
		
		//逐行处理源程序
		for( int i = 0; i < Cut.Length; ++i ) {
			if( Cut[ i ].Length == 0 ) {
				Source.Append( "\n" );
				continue;
			}
			//判断是否为宏定义指令
			if( isDefine( Cut[ i ], i, FileIndex ) ) {
				Source.Append( "\n" );
				continue;
			}
			//先执行宏替换
			Cut[ i ] = DefineNodeList.Replace( Cut[ i ] );
			
			//格式化, 注意这里之后的Line不会被写入到源代码中, 仅用于提取信息, 如#include等
			string Line = Cut[ i ].Replace( '\t', ' ' );
			Line = Line.Replace( (char)13, ' ' );
			Line = Line.Trim( ' ' );
			
			//判断是否为文件包含指令
			if( Line.StartsWith( Config.LOAD + " " ) ) {
				string FileOffsetPath = Line.Remove( 0, Config.LOAD.Length + 1 ).Trim( ' ' );
				string FileFullPath = null;
				
				//判断是否为包含当前目录
				if( FileOffsetPath.StartsWith( "\"" ) && FileOffsetPath.EndsWith( "\"" ) ) {
					FileOffsetPath = FileOffsetPath.Remove( 0, 1 );
					FileOffsetPath = FileOffsetPath.Remove( FileOffsetPath.Length - 1 );
					FileFullPath =  CurrentDir + FileOffsetPath;
				}
				//判断是否为包含库目录
				else if( FileOffsetPath.StartsWith( "<" ) && FileOffsetPath.EndsWith( ">" ) ) {
					FileOffsetPath = FileOffsetPath.Remove( 0, 1 );
					FileOffsetPath = FileOffsetPath.Remove( FileOffsetPath.Length - 1 );
					FileFullPath =  OS.ModuleLibPath + FileOffsetPath;
				}
				//都不是, 报错
				else {
					ET.WriteLineError( FileIndex, i, "[include]指令格式错误: " + Line + ", 包含当前目录文件是 #include \"filename\", 包含库文件是  #include <filename>" );
					continue;
				}
				//判断文件是否存在
				if( !Compiler.FileExists( FileFullPath ) ) {
					ET.WriteLineError( FileIndex, i, "不存在的文件: " + FileFullPath );
					continue;
				}
				//导入目标文件
				string sys = Compiler.OpenIncludeFile( FileFullPath );
				
				Source.Append( (char)1 );
				Source.Append( (char)UseFileList.GetNumber() );
				Source.Append( LoadFiles( sys, FileFullPath ) );
				Source.Append( (char)2 );
				Source.Append( "\n" );
				continue;
			}
			//判断是否为设置参数指令
			if( isCPU( Line, i ) ) {
				string TargetPath = Config.GetSystemFilePathFromCPUType();
				string sys = Compiler.OpenCompileFile( TargetPath );
				
				Source.Append( (char)1 );
				Source.Append( (char)UseFileList.GetNumber() );
				Source.Append( "public unit " + VarType.UserRootUnitName + Config.ChipNumber + "{" );
				Source.Append( LoadFiles( sys, TargetPath ) );
				Source.Append( "}" );
				Source.Append( (char)2 );
				Source.Append( "\n" );
				Config.ChipNumber += 1;
				continue;
			}
			//到这里表示普通语句
			Source.Append( Cut[ i ] + "\n" );
		}
		//删除当前文件中的定义
		DefineNodeList.Delete( FileIndex );
		
		return Source.ToString();
	}
	
	//解析设置参数指令,相当于一个小的文本引擎
	static bool isCPU( string Line, int LineIndex )
	{
		Line = FormatCode( Line );
		string Head = "#setcpu ";
		if( Line.StartsWith( Head ) ) {
			//添加CPU信息
			string Mes = Line.Remove( 0, Head.Length );
			Config.AddCPU( LineIndex, Mes );
			return true;
		}
		else {
			return false;
		}
	}
	
	//解析宏定义指令
	static bool isDefine( string Line, int LineIndex, int FileIndex )
	{
		//注意不要使用格式化器
		//Line = FormatCode( Line );
		Line = Line.Replace( '\t', ' ' );
		Line = Line.TrimStart( ' ' );
		
		string Head = "#define ";
		if( Line.StartsWith( Head ) ) {
			Line = Line.Remove( 0, Head.Length );
			int sindex = Line.IndexOf( ' ' );
			string Source = Line.Remove( sindex );
			string Target = Line.Remove( 0, sindex + 1 );
			
			//添加宏定义列表
			DefineNodeList.Add( Source, Target, FileIndex );
			
			return true;
		}
		else {
			return false;
		}
	}
	
	//小型字符串解析器, 去掉空格, 制表符等, 格式化
	static string FormatCode( string code )
	{
		code = code.Replace( '\t', ' ' );
		code = code.Trim( ' ' );
		string Line = "";
		bool LastisSpace = true;
		int Length = code.Length;
		for( int i = 0; i < Length; ++i ) {
			if( code[ i ] == ' ' ) {
				if( LastisSpace ) {
					continue;
				}
				LastisSpace = true;
			}
			else {
				LastisSpace = false;
			}
			Line += code[ i ];
		}
		return Line;
	}
	
	//宏定义列表类
	static class DefineNodeList
	{
		static DefineNode[] DefineList;
		static int DefineListLength;
		
		//初始化
		public static void Init()
		{
			DefineList = new DefineNode[ 200 ];
		}
		
		//编译复位, 每次编译开始时调用此函数
		public static void Reset()
		{
			DefineListLength = 0;
		}
		
		//添加一个宏定义
		public static void Add( string s1, string s2, int FileIndex )
		{
			int preIndex = GetIndex( s1 );
			if( preIndex == -1 ) {
				DefineList[ DefineListLength ] = new DefineNode( s1, s2, FileIndex );
				DefineListLength++;
			}
			else {
				DefineList[ preIndex ] = new DefineNode( s1, s2, FileIndex );
			}
		}
		
		//删除指定文件索引中的定义
		public static void Delete( int FileIndex )
		{
			for( int i = 0; i < DefineListLength; ++i ) {
				if( DefineList[i].Enable == 1 ) {
					DefineList[i].Enable = 0;
				}
				if( DefineList[i].FileIndex == FileIndex ) {
					
					if( DefineList[i].Enable == 2 ) {
						DefineList[i].Enable = 1;
					}
					
				}
			}
		}
		
		//替换一行程序
		public static string Replace( string Line )
		{
			for( int i = 0; i < DefineListLength; ++i ) {
				if( DefineList[i].Enable != 0 ) {
					Line = Line.Replace( DefineList[i].DefName, DefineList[i].TargetName );
				}
			}
			return Line;
		}
		
		//获取一个定义的索引
		static int GetIndex( string DefName )
		{
			for( int i = 0; i < DefineListLength; ++i ) {
				if( DefineList[i].DefName == DefName ) {
					return i;
				}
			}
			return -1;
		}
		
		//宏定义节点类
		class DefineNode
		{
			//构造函数
			public DefineNode( string s1, string s2, int findex )
			{
				FileIndex = findex;
				
				DefName = s1;
				TargetName = s2;
				
				Enable = 2;
			}
			
			public int FileIndex;
			public string DefName;
			public string TargetName;
			public int Enable;
		}
	}
}
}

